package common;

import java.io.Serializable;
import java.rmi.RemoteException;
import java.util.LinkedList;
import java.util.List;

//This class holds the game logic.
public class Game implements Serializable {
	private static final long serialVersionUID = 1L;
	private final LinkedList<Player> playerList = new LinkedList<Player>();
	private int currentPlayer; // Player 1 equals nr 0, Player 2 nr 1
								// etc...
	private int maxPlayers;
	private final GameTileList gameTileList;
	private final TileEvent tileEvent;
	private String log = "";
	private int playerWon = -1; // This will hold the number of the player that
								// has won the game

	public Game(final int numberOfClients) {
		this.currentPlayer = 0;
		this.maxPlayers = numberOfClients;
		this.gameTileList = new GameTileList();
		this.tileEvent = new TileEvent(this);
	}

	public int getNumberOfPlayers() {
		return this.maxPlayers;
	}

	public LinkedList<Tile> getGameTileList() {
		return this.gameTileList.getTileList();
	}

	public void setMaxPlayers(final int i) {
		this.maxPlayers = i;
	}

	public void addPlayer(final ServerInterface server) {
		this.playerList.add(new Player());
	}

	public void diceRolled(final ServerInterface server, final int player)
			throws RemoteException {
		final int i = ThrowDices.random();
		this.playerList.get(player).diceRolled(i, this);
		getPlayer(getCurrentPlayer()).setCurrentCardViewed("moveCard");
		server.update(player, this);

	}

	public void tileChosen(final ServerInterface server, final int i,
			final int player) throws RemoteException {
		final Tile tile = getGameTileList().get(i);
		this.playerList.get(player).tileChoosen(tile);
		this.playerList.get(player).setCurrentCardViewed(
				"drawnAdventureCardsCard");

		server.update(player, this);
	}

	public void tileEvent(final ServerInterface server, final int player)
			throws RemoteException {
		this.playerList.get(player).getGameBoard().getCurrentTile()
				.tileEvent(this, player);
		server.update(player, this);
	}

	public void tileEventContinue(final ServerInterface server, final int player)
			throws RemoteException {
		final boolean shouldDrawMore = this.playerList.get(player)
				.getGameBoard().getCurrentTile()
				.tileEventContinue(this, player);
		// If shouldDrawMore == false, turn is over.
		if (shouldDrawMore == false) {
			nextPlayer();
		}
		server.update(player, this);
	}

	public Player getPlayer(final int player) {
		return this.playerList.get(player);
	}

	public void requestUpdate(final ServerInterface server, final int player)
			throws RemoteException {
		server.update(player, this);
	}

	public int getCurrentPlayer() {
		return this.currentPlayer;
	}

	public void nextPlayer() {
		this.playerList.get(getCurrentPlayer()).setCurrentCardViewed(
				"turnEndedCard");
		addToLog("----------"
				+ this.playerList.get(getCurrentPlayer()).getName()
				+ "'s turn has ended. " + "----------\n\n");

		this.currentPlayer = this.currentPlayer + 1;
		if (this.currentPlayer == this.maxPlayers) {
			this.currentPlayer = 0;
		}

		this.playerList.get(this.currentPlayer).setHasDrawnCardThisTurn(false);
		this.playerList.get(getCurrentPlayer())
				.setCurrentCardViewed("moveCard");

		addToLog("It is now "
				+ this.playerList.get(this.currentPlayer).getName()
				+ "'s turn.\n");
	}

	public List<Player> getPlayerList() {
		return this.playerList;
	}

	public List<Integer> getPlayerPositions() {
		final List<Integer> positions = new LinkedList<Integer>();
		for (int i = 0; i < this.playerList.size(); i++) {
			positions.add(this.playerList.get(i).getGameBoard()
					.getCurrentTile().position());
		}
		return positions;
	}

	public TileEvent getTileEvent() {
		return this.tileEvent;
	}

	public String getLog() {
		return this.log;
	}

	public void addToLog(final String txt) {
		this.log = this.log.concat(txt);
	}

	public void setPlayerWon(final int i) {
		this.playerWon = i;
	}

	public int getPlayerWon() {
		return this.playerWon;
	}

}
